#include <cmath>

#include "vector.h"

Vector::Vector( void ) {
    for( unsigned int i = 0; i < 4; i++ )
        data[i] = 0.0;
}

Vector::Vector( float * incoming ) {
    for( unsigned int i = 0; i < 4; i++ )
        data[i] = incoming[i];
}

Vector::Vector( float x, float y, float z, float w ) {
    data[0] = x;
    data[1] = y;
    data[2] = z;
    data[3] = w;
}

float Vector::at( unsigned int i ) const {
    return data[i];
}

Vector & Vector::normalize( void ) {
    *this /= std::sqrt( Vector::dotProduct( *this, *this ) );
    return *this;
}

float & Vector::operator[]( unsigned int i ) {
    return data[i];
}

Vector & Vector::operator+=( const Vector & vect ) {
    data[0] += vect.data[0];
    data[1] += vect.data[1];
    data[2] += vect.data[2];
    data[3] += vect.data[3];

    return *this;
}

Vector Vector::operator+( const Vector & vect ) const {
    Vector result = *this;
    result += vect;
    return result;
}

Vector & Vector::operator-=( const Vector & vect ) {
    data[0] -= vect.data[0];
    data[1] -= vect.data[1];
    data[2] -= vect.data[2];
    data[3] -= vect.data[3];

    return *this;
}

Vector & Vector::operator*=( float f ) {
    data[0] *= f;
    data[1] *= f;
    data[2] *= f;
    data[3] *= f;

    return *this;
}

Vector & Vector::operator/=( float f ) {
    data[0] /= f;
    data[1] /= f;
    data[2] /= f;
    data[3] /= f;

    return *this;
}

Vector Vector::operator*( float f ) const {
    Vector result = *this;
    result *= f;
    return result;
}

Vector Vector::operator/( float f ) const {
    Vector result = *this;
    result /= f;
    return result;
}

Vector Vector::operator-( const Vector & vect ) const {
    Vector result = *this;
    result -= vect;
    return result;
}

bool Vector::operator==( const Vector & vect ) const {
    for( unsigned int i = 0; i < 4; i++ ) {
        if ( data[i] != vect.data[i] )
            return false;
    }
    return true;
}
bool Vector::equals( const Vector & vect, float threshold ) const {
    for( unsigned int i = 0; i < 4; i++ ) {
        if ( data[i] <= vect.data[i] - threshold || data[i] >= vect.data[i] + threshold )
            return false;
    }
    return true;
}

Vector Vector::operator-( void ) const {
    Vector result = *this;
    for ( unsigned int i = 0; i < 4; i++ )
        result[i] = -result[i];
    return result;
}

std::ostream & operator<<( std::ostream & out, const Vector & vect ) {
    out << "{";

    for( unsigned int i = 0; i < 4; i++ ) {
        out << " " << vect.data[i];

        if ( i > 3 )
            out << ",";
    }

    out << " }";

    return out;
}

float Vector::dotProduct( const Vector & vect, const Vector & vect2 ) {
    float out = 0;

    for ( unsigned int i = 0; i < 4; i++ ) {
        out += vect.data[i] * vect2.data[i];
    }

    return out;
}

Vector Vector::normalize( const Vector & vect ) {
    Vector result = vect;
    result.normalize();
    return result;
}
